--- title: "04-SecurityUtils 使用示例" created: 2025-12-03 tags: - 项目 aliases: - SecurityUtils 使用示例 --- # SecurityUtils 使用示例 ## 场景一:获取用户信息 ### 1.1 获取用户(可能为 null) ```java @GetMapping("/user/info") public ResponseEntity getUserInfo() { LoginUserVO user = SecurityUtils.getLoginUser(); if (user == null) { return ResponseEntity.ok(Map.of("message", "请先登录")); } return ResponseEntity.ok(user); } ``` ### 1.2 获取用户(必须登录) ```java @PostMapping("/like") public ResponseEntity likeArticle(@RequestParam Long articleId) { // 此方法需要用户已登录 LoginUserVO user = SecurityUtils.requireLoginUser(); // 未登录时抛异常 Long userId = user.getId(); articleService.like(articleId, userId); return ResponseEntity.ok("点赞成功"); } ``` ### 1.3 简化获取用户 ID ```java @PostMapping("/comment") public ResponseEntity createComment(@RequestBody CommentRequest request) { // 直接获取用户 ID(简化写法) Long userId = SecurityUtils.requireUserId(); Comment comment = new Comment(); comment.setUserId(userId); comment.setContent(request.getContent()); commentService.save(comment); return ResponseEntity.ok("评论成功"); } ``` ## 场景二:权限校验(失败抛异常) ### 2.1 单个权限检查 ```java @PostMapping("/users") public ResponseEntity createUser(@RequestBody CreateUserRequest request) { // 需要 system:user:add 权限,没有则抛异常 SecurityUtils.checkPermission("system:user:add"); User user = userService.createUser(request); return ResponseEntity.ok(user); } ``` ### 2.2 多权限检查(AND 逻辑) ```java @PostMapping("/publish-article") public ResponseEntity publishArticle(@RequestBody ArticleRequest request) { // 需要同时拥有 content:create 和 content:publish 权限 SecurityUtils.checkPermission("content:create", "content:publish"); Article article = articleService.createAndPublish(request); return ResponseEntity.ok(article); } ``` ### 2.3 多权限检查(OR 逻辑) ```java @PostMapping("/review-content") public ResponseEntity reviewContent(@RequestBody ReviewRequest request) { // 拥有任一权限即可:审核或发布权限 SecurityUtils.checkAnyPermission("content:review", "content:publish"); contentService.review(request); return ResponseEntity.ok("审核成功"); } ``` ### 2.4 角色检查 ```java @GetMapping("/admin/dashboard") public ResponseEntity getAdminDashboard() { // 需要 admin 角色 SecurityUtils.checkRole("admin"); return ResponseEntity.ok(adminService.getDashboard()); } ``` ### 2.5 多角色检查(OR 逻辑) ```java @GetMapping("/system/logs") public ResponseEntity getSystemLogs() { // 拥有任一角色即可:管理员或超级管理员 SecurityUtils.checkAnyRole("admin", "super_admin"); return ResponseEntity.ok(logService.getLogs()); } ``` ## 场景三:权限判断(返回 boolean) ### 3.1 条件显示功能 ```java @GetMapping("/article/{id}") public ResponseEntity getArticle(@PathVariable Long id) { Article article = articleService.getById(id); // 判断当前用户是否可以编辑此文章 boolean canEdit = SecurityUtils.hasPermission("content:edit") && article.getUserId().equals(SecurityUtils.getUserId()); // 判断当前用户是否是管理员 boolean isAdmin = SecurityUtils.isAdmin(); return ResponseEntity.ok(Map.of( "article", article, "canEdit", canEdit, "isAdmin", isAdmin )); } ``` ### 3.2 动态菜单根据权限显示 ```java @GetMapping("/menu") public ResponseEntity getMenu() { List menus = new ArrayList<>(); // 基础菜单(所有人都有) menus.add(new MenuItem("首页", "/home")); menus.add(new MenuItem("个人资料", "/profile")); // 根据权限添加菜单 if (SecurityUtils.hasPermission("content:create")) { menus.add(new MenuItem("创建内容", "/create")); } if (SecurityUtils.hasPermission("content:review")) { menus.add(new MenuItem("内容审核", "/review")); } if (SecurityUtils.isAdmin()) { menus.add(new MenuItem("用户管理", "/admin/users")); menus.add(new MenuItem("系统配置", "/admin/config")); } return ResponseEntity.ok(menus); } ``` ## 场景四:数据级权限(个人隐私数据) ### 4.1 只能查看自己的信息 ```java @GetMapping("/user/{userId}/profile") public ResponseEntity getProfile(@PathVariable Long userId) { // 检查:只有本人或管理员才能查看个人资料 SecurityUtils.checkSelfOrAdmin(userId); UserVO profile = userService.getProfile(userId); return ResponseEntity.ok(profile); } ``` ### 4.2 修改个人信息 ```java @PutMapping("/user/{userId}/profile") public ResponseEntity updateProfile( @PathVariable Long userId, @RequestBody UpdateProfileRequest request) { // 权限检查:只能修改自己的信息 SecurityUtils.checkSelfOrAdmin(userId); userService.updateProfile(userId, request); return ResponseEntity.ok("修改成功"); } ``` ### 4.3 删除账户 ```java @DeleteMapping("/user/{userId}") public ResponseEntity deleteAccount(@PathVariable Long userId) { // 权限检查:只有本人或超级管理员可以删除账户 SecurityUtils.checkSelfOrAnyAdmin(userId); userService.deleteAccount(userId); return ResponseEntity.ok("账户已删除"); } ``` ## 场景五:资源所有权检查 ### 5.1 删除自己的文章 ```java @Service public class ArticleService { public void deleteArticle(Long articleId) { Article article = articleRepository.findById(articleId); if (article == null) { throw new BusinessException(ErrorCode.NOT_FOUND, "文章不存在"); } // 检查所有权:只有创建者能删除 SecurityUtils.checkOwner(article.getUserId()); articleRepository.delete(article); log.info("文章删除成功,articleId: {}", articleId); } } ``` ### 5.2 删除评论 ```java @Service public class CommentService { public void deleteComment(Long commentId) { Comment comment = commentRepository.findById(commentId); if (comment == null) { throw new BusinessException(ErrorCode.NOT_FOUND, "评论不存在"); } // 权限检查:评论作者或文章作者或管理员可以删除 Long currentUserId = SecurityUtils.requireUserId(); Long commentAuthorId = comment.getUserId(); Article article = articleRepository.findById(comment.getArticleId()); Long articleAuthorId = article.getUserId(); boolean isCommentAuthor = currentUserId.equals(commentAuthorId); boolean isArticleAuthor = currentUserId.equals(articleAuthorId); boolean isAdmin = SecurityUtils.isAdmin(); if (!isCommentAuthor && !isArticleAuthor && !isAdmin) { throw new BusinessException(ErrorCode.FORBIDDEN, "无权删除此评论"); } commentRepository.delete(comment); } } ``` ## 场景六:Service 层权限检查 ### 6.1 在 Service 中检查权限 ```java @Service @Slf4j public class OrderService { /** * 创建订单 - 在 Service 中检查权限 */ public OrderVO createOrder(CreateOrderRequest request) { // 检查权限(也可以在 Controller 中检查) SecurityUtils.checkPermission("order:create"); Long userId = SecurityUtils.requireUserId(); Order order = new Order(); order.setUserId(userId); order.setItems(request.getItems()); orderRepository.save(order); log.info("订单创建成功,userId: {}, orderId: {}", userId, order.getId()); return OrderVO.fromEntity(order); } /** * 修改订单 - 数据级权限检查 */ public void updateOrder(Long orderId, UpdateOrderRequest request) { Order order = orderRepository.findById(orderId); if (order == null) { throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在"); } // 检查权限:只有订单所有者或管理员可以修改 SecurityUtils.checkSelfOrAdmin(order.getUserId()); order.setStatus(request.getStatus()); orderRepository.save(order); log.info("订单修改成功,orderId: {}", orderId); } /** * 查看订单 - 数据级权限检查 */ public OrderVO getOrder(Long orderId) { Order order = orderRepository.findById(orderId); if (order == null) { throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在"); } // 检查权限:只有订单所有者或管理员可以查看 SecurityUtils.checkSelfOrAdmin(order.getUserId()); return OrderVO.fromEntity(order); } /** * 导出订单 - 权限检查 */ public void exportOrders(List orderIds) { // 检查是否有导出权限 if (!SecurityUtils.hasPermission("order:export")) { throw new BusinessException(ErrorCode.FORBIDDEN, "没有导出权限"); } // 执行导出逻辑 performExport(orderIds); } } ``` ## 场景七:认证状态检查 ### 7.1 需要登录的操作 ```java @PostMapping("/favorite") public ResponseEntity addFavorite(@RequestParam Long articleId) { // 强制要求用户已登录 SecurityUtils.requireAuthenticated(); Long userId = SecurityUtils.getUserId(); favoriteService.addFavorite(userId, articleId); return ResponseEntity.ok("已收藏"); } ``` ### 7.2 不能登录的操作 ```java @PostMapping("/auth/login") public ResponseEntity login(@RequestBody LoginRequest request) { // 防止重复登录 SecurityUtils.requireNotAuthenticated(); UserVO user = userService.login(request); return ResponseEntity.ok(user); } ``` ### 7.3 条件性功能 ```java @GetMapping("/article/{id}") public ResponseEntity getArticle(@PathVariable Long id) { Article article = articleService.getById(id); Map response = new HashMap<>(); response.put("article", article); // 只有已登录用户才能看到点赞按钮 if (SecurityUtils.isAuthenticated()) { Long userId = SecurityUtils.getUserId(); boolean liked = favoriteService.isLiked(userId, id); response.put("liked", liked); response.put("canComment", true); } else { response.put("message", "请登录后进行点赞和评论"); } return ResponseEntity.ok(response); } ``` ## 最佳实践 ✅ **DO(该做的)** 1. **使用** `requireLoginUser()` **而不是** `getLoginUser()` ```java // ✅ 好:明确要求用户已登录 LoginUserVO user = SecurityUtils.requireLoginUser(); // ❌ 不好:需要额外的 null 检查 LoginUserVO user = SecurityUtils.getLoginUser(); if (user == null) { ... } ``` 2. **在 Controller 中进行权限校验** ```java // ✅ 好:权限校验在 Controller 层 @PostMapping("/users") public ResponseEntity createUser() { SecurityUtils.checkPermission("system:user:add"); return ResponseEntity.ok(userService.createUser(...)); } ``` 3. **在 Service 中进行数据级权限检查** ```java // ✅ 好:数据权限检查在 Service 层 public void updateOrder(Long orderId) { Order order = orderRepository.findById(orderId); SecurityUtils.checkSelfOrAdmin(order.getUserId()); // 执行更新 } ``` 4. **使用具体的权限码** ```java // ✅ 好:使用常量避免拼写错误 public static final String PERMISSION_USER_ADD = "system:user:add"; SecurityUtils.checkPermission(PERMISSION_USER_ADD); ``` ❌ **DON'T(不该做的)** 1. **直接使用 getLoginUser() 而忘记 null 检查** 2. **权限校验在多个地方重复** 3. **使用硬编码的权限字符串** 4. **忘记进行数据级权限检查** ## 权限常量定义 ```java public class PermissionConstants { // 用户管理 public static final String USER_ADD = "system:user:add"; public static final String USER_EDIT = "system:user:edit"; public static final String USER_DELETE = "system:user:delete"; public static final String USER_VIEW = "system:user:view"; // 内容管理 public static final String CONTENT_CREATE = "content:create"; public static final String CONTENT_EDIT = "content:edit"; public static final String CONTENT_DELETE = "content:delete"; public static final String CONTENT_PUBLISH = "content:publish"; public static final String CONTENT_REVIEW = "content:review"; // 订单管理 public static final String ORDER_CREATE = "order:create"; public static final String ORDER_EXPORT = "order:export"; public static final String ORDER_CANCEL = "order:cancel"; } // 在 Controller 中使用 @PostMapping("/users") public ResponseEntity createUser() { SecurityUtils.checkPermission(PermissionConstants.USER_ADD); return ResponseEntity.ok(userService.createUser(...)); } ``` --- **项目分区导航**:⬅️ [[03-权限校验最佳实践模型代码|03-权限校验最佳实践模型代码]] | 04-SecurityUtils 使用示例 | ➡️ [[05-权限控制模型|05-权限控制模型]]